/*
 * 代号：凤凰
 * http://www.jphenix.org
 * 2016年11月23日
 * V4.0
 */
package com.jphenix.driver.cluster;

import com.jphenix.driver.threadpool.ThreadSession;
import com.jphenix.kernel.baseobject.instanceb.ABase;
import com.jphenix.standard.docs.ClassInfo;
import com.jphenix.standard.servlet.IActionContext;
import com.jphenix.standard.servlet.ICluster;
import com.jphenix.standard.servlet.IRequest;
import com.jphenix.standard.servlet.IServletConst;

import java.io.InputStream;
import java.util.List;
import java.util.Map;

/**
 * 非集群模式下返回该类
 * 
 * 2018-05-25 增加了 group() 获取当前服务器所在分组名方法
 * 2018-06-28 增加了判断本次请求是否由集群内部服务器发起的方法
 * 2018-07-26 增加了返回当前服务器时间校准差值
 * 2018-12-13 增加了一个接口中的方法
 * 2019-01-31 在调用集群方法时，把调用者类信息传入，方便在日志中查看调用者
 * 2019-06-26 按照新的接口修改了内部
 * 2019-08-03 按照新的接口修改了内部
 * 2019-10-02 增加了两个无用方法
 * 2019-12-10 增加了个无用方法
 * 
 * @author MBG
 * 2016年11月23日
 */
@ClassInfo({"2019-12-10 18:05","非集群模式下返回该类"})
public class NoCluster extends ABase implements ICluster {

	/**
	 * 构造函数
	 * @author MBG
	 */
	public NoCluster(ABase base) {
		super();
	}
	
	/**
	 * 获取当前服务器的名字（非集群时，只返回固定值）
	 * @return 当前服务器名字
	 * 2016年11月19日
	 * @author MBG
	 */
	@Override
	public String name() {
		return "PX";
	}
	
	/**
	 * 获取当前服务器所在的群组
	 * @return 当前服务器所在的群组
	 * 2017年4月21日
	 * @author MBG
	 */
	@Override
    public String group() {
		return "";
	}

	/**
	 * 集群服务器时间
	 * @return 当前服务器时间
	 * 2016年11月19日
	 * @author MBG
	 */
	@Override
	public long time() {
		return System.currentTimeMillis();
	}
	
	/**
	 * 返回当前服务器时间校准差值
	 * @return 当前服务器时间校准差值
	 * 2018年7月26日
	 * @author MBG
	 */
	@Override
    public long amendTime() {
		return 0;
	}

	/**
	 * 判断是否由集群成员调用的 只允许本机调用
	 * 动作上下文（request，response）是从线程会话中获取的。
	 * 所以不支持服务类，只支持动作类
	 * IServletConst.KEY_ACTION_CONTEXT
	 * @return 是否本机调用
	 * 2016年11月20日
	 * @author MBG
	 */
	@Override
	public boolean check() {
        //获取线程会话
        IActionContext ac = 
        		(IActionContext)ThreadSession.get(IServletConst.KEY_ACTION_CONTEXT);
        return check(ac);
	}
	
	/**
	 * 判断是否由集群成员调用的 只允许本机调用
	 * 动作上下文（request，response）是从线程会话中获取的。
	 * 所以不支持服务类，只支持动作类
	 * IServletConst.KEY_ACTION_CONTEXT
	 * @return 是否本机调用
	 * 2016年11月20日
	 * @author MBG
	 */
	@Override
	public boolean check(IActionContext ac) {
        if(ac==null) {
        	return false;
        }
        return "127.0.0.1".equals(ac.getRemoteAddress());
	}

	/**
	 * 返回当前服务器是否为主服务器
	 * @return 永远返回真
	 * 2016年11月21日
	 * @author MBG
	 */
	@Override
	public boolean master() {
		return true;
	}

	/**
	 * 调用主服务器动作
	 * @param scriptId 脚本主键
	 * @param param    提交对象
	 * @param callType 调用方式  0普通调用  1调用调用主服务器  2广播调用
	 * @return         返回结果
	 * @throws  Exception  异常
	 * 2016年11月20日
	 * @author MBG
	 */
	@Override
	public <T> T call(String scriptId, Object param,int callType) throws Exception {
		throw new Exception("执行出错，不能以集群方式调用本机服务");
		/*
		if(scriptId==null || scriptId.length()<1) {
			return null;
		}
		try {
			if(param==null) {
				return sl.invokeScript(this,scriptId);
			}else if(param instanceof IActionContext) {
				return sl.invokeScript(this,scriptId,(IActionContext)param);
			}else {
				return sl.invokeScriptByObjPara(this,scriptId,param);
			}
		}catch(Exception e) {
			e.printStackTrace();
		}
		return null;
		*/
	}

	/**
	 * 调用主服务器动作
	 * @param scriptId 脚本主键
	 * @param callType 调用方式  0普通调用  1调用调用主服务器  2广播调用
	 * @return 返回结果 
	 * @throws Exception 异常
	 * 2016年11月20日
	 * @author MBG
	 */
	@Override
	public <T> T call(String scriptId,int callType) throws Exception {
		return call(scriptId,null,0);
	}

	/**
	 * 广播集群中所有服务器
	 * 单机运行，没有要广播的其它的服务器
	 * @param scriptId 脚本主键 
	 * @param param    提交参数
	 * 2016年11月21日
	 * @author MBG
	 */
	@Override
	public void callAll(String scriptId, Object param) {}

	/**
	 * 广播集群中所有服务器
	 * 单机运行，没有要广播的其它的服务器
	 * @param scriptId 脚本主键 
	 * 2016年11月21日
	 * @author MBG
	 */
	@Override
	public void callAll(String scriptId) {}
	
	/**
	 * 是否为集群模式
	 * @return 是否为集群模式
	 * 2016年11月28日
	 * @author MBG
	 */
	@Override
    public boolean clusterMode() {
		return false;
	}
	
    /**
     * 动作路径扩展名
     */
	public String getFilterActionExtName() {
		return "ha";
	}
	
	/**
	 * 集群服务器索引（当前服务器在集群服务器中的位置）
	 * @return 集群服务器索引
	 * 2016年12月11日
	 * @author MBG
	 */
	@Override
    public int index() {
		return 0;
	}
	
	/**
	 * 覆盖函数
	 */
	@Override
    public String toString() {
		return "NoCluster_"+hashCode();
	}

	/**
	 * 是否禁用
	 * @return 是否禁用
	 * 2017年4月26日
	 * @author MBG
	 */
	@Override
    public boolean disabled() {
		return true;
	}

	/**
	 * 获取指定群组中的主服务器
	 * @param groupName 群组名
	 * @return 主服务器信息
	 * 2017年4月21日
	 * @author MBG
	 */
	@Override
    public ServerInfoVO getMasterServer(String groupName) {
		return null;
	}

	/**
	 * 判断请求
	 * @param req     页面请求
	 * @return            是否允许访问
	 * 2017年5月2日
	 * @author MBG
	 */
	@Override
    public boolean allow(IRequest req) {
		return false;
	}

	/**
	 * 判断请求
	 * @param ip     客户端IP地址
	 * @return            是否允许访问
	 * 2017年5月2日
	 * @author MBG
	 */
	@Override
    public boolean allow(String ip) {
		return false;
	}
	
	/**
	 * 判断本次调用是否由集群中的服务器发起
	 * @param req    请求对象
	 * @return       是否由集群中的服务器发起
	 * 2018年6月28日
	 * @author MBG
	 */
	@Override
    public boolean callFromCluster(IRequest req) {
		return false;
	}
	
	/**
	 * 调用其他服务器上的脚本程序
	 * @param keyName           目标群组名或者指定服务器名
	 * @param scriptId          目标脚本名
	 * @param param             传入参数
	 * @param callType          调用方式  0主服务器调用  1广播调用
	 * @param invoker           调用者
	 * @param noReturnValue     是否不需要返回值 
	 *                         （因为是目标服务器，本机是无法通过脚本信息类判定目标脚本带不带返回值，只能手工强制无需返回值） 
	 *                          这中情况主要用于反向应触发调用服务，只要通知前置机，无需获取返回值。这样就无需轮询等待返回值，使远程调用
	 * @return                  调用返回值
	 * @throws Exception        异常
	 * 2017年4月22日
	 * @author MBG
	 */
	@Override
    public Object routeCall(
			String keyName
			,String scriptId
			,Object param
			,int callType
			,Object invoker
			,boolean noReturnValue) throws Exception{
		return null;
	}

	/**
	 * 获取指定服务器（无用）
	 * @param serverName 服务器名
	 * @return　　　　　　　服务器URL
	 * 2019年8月3日
	 * @author MBG
	 */
	@Deprecated
	@Override
	public String getServerUrl(String serverName) {
		return null;
	}
	
	/**
	 * 调用目标内部触发器 (调用的目标只能是当前同样的类）（无用）
	 * @param siVO         目标服务器信息类
	 * @param param        提交参数对象
	 * @param contentType  0html  1xml  2json
	 * @param caller       调用者（当前类实例）
	 * @return             返回信息读入流
	 * 2019年10月8日
	 * @author MBG
	 */
	@Deprecated
	@Override
	public InputStream triggerCall(
			 ServerInfoVO       siVO
			,Object             param
			,Map<String,String> header
			,int                contentType
			,IClusterTrigger    caller) throws Exception {
		return null;
	}

	/**
	 * 调用目标服务器
	 * @param serverKey  服务器主键（名）（无用）
	 * @param scriptId   脚本主键
	 * @param param      传入参数
	 * @param callType   调用方式  0普通集群调用  1调用调用主服务器  2广播调用
	 * @return 返回信息
	 * @throws Exception 异常
	 * 2017年3月29日
	 * @author MBG
	 */
	@Deprecated
	@Override
	public Object call(String serverKey, String scriptId, Object param, int callType) throws Exception {
		return null;
	}

	/**
	 * 以文件上传方式
	 * @param keyName         目标服务器主键或目标群组主键
	 * @param scriptId        调用目标脚本
	 * @param params          提交参数字符串 key1=val1&key2=val2
	 * @param uploadNameList  上传文件对象名（目标脚本参数名）序列
	 * @param fileNameList    源文件名序列
	 * @param filePathList    需要上传的文件绝对路径序列
	 * @param invoker         调用者
	 * @return                返回字符串信息
	 * @throws Exception      异常
	 * 2019年12月10日
	 * @author MBG
	 */
	@Deprecated
	@Override
	public String routeUpload(String keyName, String scriptId, String params, List<String> uploadNameList,
			List<String> fileNameList, List<String> filePathList, Object invoker) throws Exception {
		return null;
	}
}
